﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Framework.Components
{
    /// <summary>
    /// 数据库参数解析器
    /// </summary>
    public class SqlParamParser
    {
        private LimitParser limitParser;
        private List<OrderParser> orderParsers = new List<OrderParser>();
        private List<WhereParser> whereParsers = new List<WhereParser>();

        public SqlParamParser()
        {
            limitParser = new LimitParser("offset", "size");
        }

        public SqlParamParser(params object[] args)
        {
            // 遍历参数
            int asize = (args != null) ? args.Length : 0;
            for (int i = 0; i < asize; i++)
            {
                object obj = args[i];
                if (typeof(LimitParser).IsInstanceOfType(obj))
                {
                    limitParser = (LimitParser)obj;
                    continue;
                }
                else if (typeof(OrderParser).IsInstanceOfType(obj))
                {
                    orderParsers.Add((OrderParser)obj);
                    continue;
                }
                else if (typeof(WhereParser).IsInstanceOfType(obj))
                {
                    whereParsers.Add((WhereParser)obj);
                    continue;
                }
                Log.Error("错误筛选器!" + obj, true);
            }
        }

        /// <summary>
        /// 解析
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="args"></param>
        /// <returns></returns>
        public ParseResult Parse<T>(Dictionary<string, T> args)
        {
            ParseResult result = new ParseResult();

            // where 筛选语句
            result.WhereStr = "";
            int wsize = (whereParsers != null) ? whereParsers.Count : 0;
            if (wsize > 0)
            {
                StringBuilder strBdr = new StringBuilder();
                int scount = 0;
                // 遍历拼接
                strBdr.Append("where ");
                for (int i = 0; i < wsize; i++)
                {
                    // 解析处理
                    WhereParser whereParser = whereParsers[i];
                    string vstr = whereParser.Parse(args);
                    if (string.IsNullOrEmpty(vstr)) { continue; }
                    // 拼接处理
                    if (scount > 0)
                    {
                        strBdr.Append(" and ");
                    }
                    strBdr.Append(vstr);
                    scount++;
                }
                // 有条件就添加
                if (scount > 0)
                {
                    result.WhereStr = strBdr.ToString();
                }
            }

            // 排序筛选
            result.OrderStr = "";
            int osize = (orderParsers != null) ? orderParsers.Count : 0;
            if (osize > 0)
            {
                StringBuilder strBdr = new StringBuilder();
                strBdr.Append("order by ");
                for (int i = 0; i < osize; i++)
                {
                    if (i > 0)
                    {
                        strBdr.Append(",");
                    }
                    OrderParser orderParser = orderParsers[i];
                    strBdr.Append(orderParser.Parse(args));
                }
                result.OrderStr = strBdr.ToString();
            }

            // 数量筛选
            result.LimitStr = limitParser.Parse(args);

            // 返回结果
            result.Code = Result.SUCCESS;
            return result;
        }


        /// <summary>
        /// 获取字符串
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        private static string GetString<T>(Dictionary<string, T> args, string key)
        {
            if (args == null) { return null; }
            if (!args.ContainsKey(key)) { return null; }
            T value = args[key];
            return (value != null) ? value.ToString() : null;
        }

        /// <summary>
        /// 解析结果
        /// </summary>
        public class ParseResult : Result
        {
            /// <summary>
            /// 数量筛选语句
            /// </summary>
            public string LimitStr { get; set; }

            /// <summary>
            /// 条件筛选语句
            /// </summary>
            public string WhereStr { get; set; }

            /// <summary>
            /// 排序筛选语句
            /// </summary>
            public string OrderStr { get; set; }

            /// <summary>
            /// 创建错误消息
            /// </summary>
            /// <param name="msg"></param>
            /// <returns></returns>
            public static new ParseResult Error(string msg)
            {
                ParseResult result = new ParseResult();
                result.Code = ERROR;
                result.Msg = msg;
                return result;
            }
        }


        /// <summary>
        /// limit解析器
        /// </summary>
        public class LimitParser
        {
            protected string offsetKey; // 参数key
            protected string sizeKey;  // 参数key 

            public LimitParser(string offsetKey, string sizeKey)
            {
                this.offsetKey = offsetKey;
                this.sizeKey = sizeKey;
            }

            /// <summary>
            /// 解析
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="args"></param>
            /// <returns></returns>
            public string Parse<T>(Dictionary<string, T> args)
            {
                // 数量筛选
                int offset = Utils.Utils.ToValue<int>(GetString(args, offsetKey));
                int size = Utils.Utils.ToValue<int>(GetString(args, sizeKey));
                size = Math.Max(1, Math.Min(size, 100));
                return string.Format("limit {0},{1}", offset, size);
            }
        }

        /// <summary>
        /// order解析器
        /// </summary>
        public class OrderParser
        {
            protected string sqlKey;    // 数据库key
            protected string paramKey;  // 参数key, 是否正序
            protected bool reverse;       // 倒序

            public OrderParser(string sqlKey, string paramKey, bool reverse)
            {
                this.sqlKey = sqlKey;
                this.paramKey = paramKey;
                this.reverse = reverse;
            }

            public OrderParser(string sqlKey, string paramKey):this(sqlKey, paramKey, false) { }

            /// <summary>
            /// 解析
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="args"></param>
            /// <returns></returns>
            public string Parse<T>(Dictionary<string, T> args)
            {
                bool asc = !Utils.Utils.ToValue<bool>(GetString(args, paramKey));
                if(reverse) { asc = !asc; } // 倒序处理
                return sqlKey + " " + ((asc) ? "asc" : "desc");
            }
        }

        /// <summary>
        /// where解析器
        /// </summary>
        public class WhereParser
        {
            protected string sqlKey; // 数据库key
            protected string paramKeyA; // 参数key
            protected string preciseQueryKey; // 是否精确key
          
            public WhereParser(string sqlKey, string paramKey, string preciseParamKey)
            {
                this.sqlKey = sqlKey;
                this.paramKeyA = paramKey;
                this.preciseQueryKey = preciseParamKey;
            }

            public WhereParser(string sqlKey, string paramKey) : this(sqlKey, paramKey, null) { }

            /// <summary>
            /// 解析
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="args"></param>
            /// <returns></returns>
            public virtual string Parse<T>(Dictionary<string, T> args)
            {
                // 检测是否存在key
                string key = GetString(args, paramKeyA);
                if (string.IsNullOrEmpty(key)) { return null; }
                // 拼接字符串
                StringBuilder whereBdr = new StringBuilder();
                whereBdr.Append(sqlKey);

                // 是否精确查找
                bool preciseQuery = (!string.IsNullOrEmpty(preciseQueryKey)) ? Utils.Utils.ToValue<bool>(GetString(args, preciseQueryKey)) : true;
                if (preciseQuery)
                {
                    whereBdr.Append("='");
                    whereBdr.Append(key);
                    whereBdr.Append("'");
                }
                else
                {
                    whereBdr.Append(" like '%");
                    whereBdr.Append(key);
                    whereBdr.Append("%' ");
                }
                return whereBdr.ToString();
            }
        }

        /// <summary>
        /// where解析器
        /// </summary>
        public class WhereIfParser : WhereParser
        {
            public WhereIfParser(string sqlKey, string paramKey) : base(sqlKey, paramKey, null)
            {
            }

            /// <summary>
            /// 解析
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="args"></param>
            /// <returns></returns>
            public override string Parse<T>(Dictionary<string, T> args)
            {
                // 检测是否存在key
                string key = GetString(args, paramKeyA);
                if (string.IsNullOrEmpty(key)) { return null; }
                // 拼接字符串
                StringBuilder whereBdr = new StringBuilder();

                // 是否精确查找
                bool paramBool = Utils.Utils.ToValue<bool>(key);
                if (!paramBool)
                {
                    whereBdr.Append("!");
                }
                whereBdr.Append("(");
                whereBdr.Append(sqlKey);
                whereBdr.Append(")");
                return whereBdr.ToString();
            }
        }

        /// <summary>
        /// where between 解析器
        /// </summary>
        public class WhereBetweenParser : WhereParser
        {
            public WhereBetweenParser(string sqlKey, string startParamKey, string endParamKey) : base(sqlKey, startParamKey, endParamKey)
            {
            }

            /// <summary>
            /// 解析
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="args"></param>
            /// <returns></returns>
            public override string Parse<T>(Dictionary<string, T> args)
            {
                // 检测是否存在key
                string startKey = GetString(args, paramKeyA);
                string endKey = GetString(args, preciseQueryKey);
                if (string.IsNullOrEmpty(startKey) && string.IsNullOrEmpty(endKey))
                {
                    return null;
                }

                // 拼接字符串
                StringBuilder whereBdr = new StringBuilder();
                if (!string.IsNullOrEmpty(startKey) && !string.IsNullOrEmpty(endKey))
                {
                    // 2个都有
                    if (startKey.Equals(endKey))
                    {
                        // 2个值都一样
                        whereBdr.Append(sqlKey);
                        whereBdr.Append("='");
                        whereBdr.Append(startKey);
                        whereBdr.Append("'");
                    }
                    else
                    {

                        whereBdr.Append(sqlKey);
                        whereBdr.Append(" BETWEEN '");
                        whereBdr.Append(startKey);
                        whereBdr.Append("' AND '");
                        whereBdr.Append(endKey);
                        whereBdr.Append("'");
                    }
                }
                else
                {
                    // 开始和结束其中1个缺了
                    bool start = false;
                    if (!string.IsNullOrEmpty(startKey))
                    {
                        whereBdr.Append(sqlKey);
                        whereBdr.Append(">='");
                        whereBdr.Append(startKey);
                        whereBdr.Append("'");
                        start = true;
                    }
                    if (!string.IsNullOrEmpty(endKey))
                    {
                        if (start)
                        {
                            whereBdr.Append(" and ");
                        }
                        whereBdr.Append(sqlKey);
                        whereBdr.Append("<'");
                        whereBdr.Append(endKey);
                        whereBdr.Append("'");
                    }
                }
                return whereBdr.ToString();
            }
        }
    }
}
